home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / UTIL_SRC / C016.ZIP / CALC / HOC.C next >
Text File  |  1990-01-19  |  11KB  |  459 lines

  1.  
  2. # line 17 "hoc.y"
  3. /*********************** self documentation **********************/
  4. char *sdoc = "\
  5.                                 \n\
  6. HOC - hoc [-]                            \n\
  7.                                 \n\
  8. hoc is an enhanced version 3 of Kernighan and Pike's calculator    \n\
  9. You exit by typing a ctrl-D.  It works like so:            \n\
  10. hoc                                \n\
  11. 3 + 4                                \n\
  12.     7                            \n\
  13. 3^4                                \n\
  14.     81                            \n\
  15. sqrt(#)                                \n\
  16.     9                            \n\
  17. sin(PI/6)                            \n\
  18.     .5                            \n\
  19. 3e-3 * #                            \n\
  20.     0.075                            \n\
  21. c = 5687; tmin = 1.2                        \n\
  22. c * tmin                            \n\
  23.     6824.4                            \n\
  24. ^D                                \n\
  25. # is the symbol for the last value printed.            \n\
  26. functions and constants:                    \n\
  27.                                 \n\
  28. DEG (deg/radian), E,  GAMMA (Euler), PHI (golden), PI        \n\
  29. abs, acos, asin, atan, atan2, ceil, cos, cosh, exp, floor,    \n\
  30. gamma, hypot, int, j0, j1, jn, log, log10, pow, rand, sin,    \n\
  31. sinh, sqrt, srand, tan, tanh, y0, y1, yn            \n\
  32. ";
  33. /*****************************************************************/
  34.  
  35. #include "hoc.h"
  36. #include "su.h"
  37. #include "jc.h"
  38. extern double floor(), Pow();
  39. double lastno;     /* last printed value */
  40.  
  41. # line 65 "hoc.y"
  42. typedef union  {
  43.     double    val;    /* actual value */
  44.     Symbol    *sym;    /* symbol table pointer */
  45. } YYSTYPE;
  46. # define NUMBER 257
  47. # define ENDLIST 258
  48. # define CON 259
  49. # define VAR 260
  50. # define BLTIN 261
  51. # define BLTIN2 262
  52. # define BLTIN0 263
  53. # define UNDEF 264
  54. # define UNARYMINUS 265
  55. # define UNARYPLUS 266
  56. #define yyclearin yychar = -1
  57. #define yyerrok yyerrflag = 0
  58. extern int yychar;
  59. extern short yyerrflag;
  60. #ifndef YYMAXDEPTH
  61. #define YYMAXDEPTH 150
  62. #endif
  63. YYSTYPE yylval, yyval;
  64. # define YYERRCODE 256
  65.  
  66. # line 118 "hoc.y"
  67.  
  68.     /* end of grammar */
  69.  
  70.  
  71. #include <signal.h>
  72. #include <setjmp.h>
  73. jmp_buf begin;
  74.  
  75. int    lineno = 0;
  76.  
  77. main(argc, argv)    /* hoc3 */
  78.     int argc;
  79.     char *argv[];
  80. Begin
  81.     int fpecatch(); /* floating point error catcher */
  82.  
  83.     /* Set up standard SU args */
  84.     xargc = argc; xargv = argv;
  85.  
  86.     /* Code begins - check usage */
  87.     If xargc != 1 Do
  88.         selfdoc();
  89.     Endif
  90.  
  91.     init();
  92.     setjmp(begin);
  93.     signal(SIGFPE, fpecatch);
  94.     yyparse();
  95. End
  96.  
  97.  
  98. execerror(s, t)  /* recover from runtime error */
  99. register char *s, *t;
  100. Begin
  101.     warning(s, t);
  102.     longjmp(begin, 0);
  103. End
  104.  
  105.  
  106. int fpecatch()    /* catch floating point exceptions */
  107. Begin
  108.     execerror("floating point exception", (char *) 0);
  109. End
  110.  
  111. int yylex()
  112. Begin
  113.     register int c;
  114.  
  115.     While (c = getchar()) == ' ' || c == '\t' Do
  116.         ;
  117.     Endwhile
  118.     If c == EOF Do  /* archaic yyparse uses 0 for end_of_file */
  119.         Return 0;
  120.     Endif
  121.     If c == '.' || isdigit(c) Do  /* number */
  122.         ungetc(c, stdin);
  123.         scanf("%lf", &yylval.val);
  124.         Return NUMBER;
  125.     Endif
  126.     If c == '#' Do
  127.         yylval.val = lastno;
  128.         Return NUMBER;
  129.     Endif
  130.     If isalpha(c) Do
  131.         Symbol *s;
  132.         char sbuf[100], *p = sbuf;
  133.         Loop
  134.             *p++ = c;
  135.         Exitif( (c = getchar()) == EOF || !isalnum(c) );
  136.         Endloop
  137.         ungetc(c, stdin);
  138.         *p = '\0';
  139.         If (s = lookup(sbuf)) == 0 Do
  140.             s = install(sbuf, UNDEF, 0.0);
  141.         Endif
  142.         yylval.sym = s;
  143.         Return s->type == UNDEF ? VAR : s->type;
  144.     Endif
  145.     If c == '\n' Do
  146.         lineno++;
  147.     Endif
  148.     If c == '\n' || c == ';' Do
  149.         Return ENDLIST;
  150.     Endif
  151.     Return c;
  152. End
  153.  
  154.  
  155. yyerror(s)        /* called for yacc syntax error */
  156. register char *s;
  157. Begin
  158.     warning(s, (char *) 0 );
  159. End
  160.  
  161.  
  162. warning(s, t)    /* print warning message */
  163. register char *s, *t;
  164. Begin
  165.     fprintf(stderr, "%s: %s", xargv[0], s);
  166.     If t Do
  167.         fprintf(stderr, "%s", t);
  168.     Endif
  169.     fprintf(stderr, " near line %d\n", lineno);
  170. End
  171. short yyexca[] ={
  172. -1, 1,
  173.     0, -1,
  174.     -2, 0,
  175.     };
  176. # define YYNPROD 24
  177. # define YYLAST 233
  178. short yyact[]={
  179.  
  180.   12,  23,  15,  14,  22,  13,  25,  12,  24,  43,
  181.   14,  21,  13,  28,   1,  27,  19,  17,  21,  18,
  182.   26,  20,  48,  19,  17,  21,  18,  30,  20,   3,
  183.   19,  17,  46,  18,  21,  20,   0,   0,  45,  19,
  184.   17,  21,  18,   0,  20,  44,  19,  17,  21,  18,
  185.   21,  20,   0,  19,  17,  19,  18,   0,  20,   0,
  186.   20,   0,   0,   0,   0,   0,   0,   0,  22,   0,
  187.    0,   0,   0,   0,   4,  22,   0,   0,   0,   0,
  188.    0,   0,  22,   0,   0,   0,   0,  29,  31,  32,
  189.    0,  22,  33,  34,  35,  36,  37,  38,  22,  39,
  190.   40,  41,  42,   0,   0,  22,   0,  22,   0,   0,
  191.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  192.    0,  47,   0,   0,   0,   0,   0,   0,   0,   0,
  193.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  194.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  195.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  196.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  197.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  198.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  199.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  200.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  201.    0,   0,   0,   0,   0,   0,   5,   8,   2,   6,
  202.    7,   9,  10,  11,   8,   0,   6,   7,   9,  10,
  203.   11,   0,  16 };
  204. short yypact[]={
  205.  
  206. -1000, -40,-1000,-256, -26,-257, -53, -55,-1000, -20,
  207.  -25, -27, -33, -33, -33,-1000,-1000, -33, -33, -33,
  208.  -33, -33, -33,-1000, -33, -33, -33, -33, -32,   4,
  209. -1000, -90, -90,  13,  13, -90, -90, -90, -90,  11,
  210.   11,  -3, -12,-1000,-1000,-1000, -33, -19,-1000 };
  211. short yypgo[]={
  212.  
  213.    0,  74,  27,  14 };
  214. short yyr1[]={
  215.  
  216.    0,   3,   3,   3,   3,   3,   2,   2,   1,   1,
  217.    1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
  218.    1,   1,   1,   1 };
  219. short yyr2[]={
  220.  
  221.    0,   0,   2,   3,   3,   3,   3,   3,   1,   1,
  222.    1,   4,   6,   3,   1,   3,   3,   3,   3,   3,
  223.    3,   3,   2,   2 };
  224. short yychk[]={
  225.  
  226. -1000,  -3, 258,  -2,  -1, 256, 259, 260, 257, 261,
  227.  262, 263,  40,  45,  43, 258, 258,  43,  45,  42,
  228.   47,  37,  94, 258,  61,  61,  40,  40,  40,  -1,
  229.   -2,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
  230.   -1,  -1,  -1,  41,  41,  41,  44,  -1,  41 };
  231. short yydef[]={
  232.  
  233.    1,  -2,   2,  14,   0,   0,   9,  10,   8,   0,
  234.    0,   0,   0,   0,   0,   3,   4,   0,   0,   0,
  235.    0,   0,   0,   5,   0,   0,   0,   0,   0,   0,
  236.   14,  22,  23,  15,  16,  17,  18,  19,  20,   6,
  237.    7,   0,   0,  13,  21,  11,   0,   0,  12 };
  238.  
  239. #
  240. # define YYFLAG -1000
  241. # define YYERROR goto yyerrlab
  242. # define YYACCEPT return(0)
  243. # define YYABORT return(1)
  244.  
  245. /*    parser for yacc output    */
  246.  
  247. #ifdef YYDEBUG
  248. int yydebug = 0; /* 1 for debugging */
  249. #endif
  250. YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
  251. int yychar = -1; /* current input token number */
  252. int yynerrs = 0;  /* number of errors */
  253. short yyerrflag = 0;  /* error recovery flag */
  254.  
  255. yyparse() {
  256.  
  257.     short yys[YYMAXDEPTH];
  258.     short yyj, yym;
  259.     register YYSTYPE *yypvt;
  260.     register short yystate, *yyps, yyn;
  261.     register YYSTYPE *yypv;
  262.     register short *yyxi;
  263.  
  264.     yystate = 0;
  265.     yychar = -1;
  266.     yynerrs = 0;
  267.     yyerrflag = 0;
  268.     yyps= &yys[-1];
  269.     yypv= &yyv[-1];
  270.  
  271.  yystack:    /* put a state and value onto the stack */
  272.  
  273. #ifdef YYDEBUG
  274.     if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
  275. #endif
  276.         if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
  277.         *yyps = yystate;
  278.         ++yypv;
  279.         *yypv = yyval;
  280.  
  281.  yynewstate:
  282.  
  283.     yyn = yypact[yystate];
  284.  
  285.     if( yyn<= YYFLAG ) goto yydefault; /* simple state */
  286.  
  287.     if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
  288.     if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
  289.  
  290.     if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
  291.         yychar = -1;
  292.         yyval = yylval;
  293.         yystate = yyn;
  294.         if( yyerrflag > 0 ) --yyerrflag;
  295.         goto yystack;
  296.         }
  297.  
  298.  yydefault:
  299.     /* default state action */
  300.  
  301.     if( (yyn=yydef[yystate]) == -2 ) {
  302.         if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
  303.         /* look through exception table */
  304.  
  305.         for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
  306.  
  307.         while( *(yyxi+=2) >= 0 ){
  308.             if( *yyxi == yychar ) break;
  309.             }
  310.         if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
  311.         }
  312.  
  313.     if( yyn == 0 ){ /* error */
  314.         /* error ... attempt to resume parsing */
  315.  
  316.         switch( yyerrflag ){
  317.  
  318.         case 0:   /* brand new error */
  319.  
  320.             yyerror( "syntax error" );
  321.         yyerrlab:
  322.             ++yynerrs;
  323.  
  324.         case 1:
  325.         case 2: /* incompletely recovered error ... try again */
  326.  
  327.             yyerrflag = 3;
  328.  
  329.             /* find a state where "error" is a legal shift action */
  330.  
  331.             while ( yyps >= yys ) {
  332.                yyn = yypact[*yyps] + YYERRCODE;
  333.                if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
  334.                   yystate = yyact[yyn];  /* simulate a shift of "error" */
  335.                   goto yystack;
  336.                   }
  337.                yyn = yypact[*yyps];
  338.  
  339.                /* the current yyps has no shift onn "error", pop stack */
  340.  
  341. #ifdef YYDEBUG
  342.                if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
  343. #endif
  344.                --yyps;
  345.                --yypv;
  346.                }
  347.  
  348.             /* there is no state on the stack with an error shift ... abort */
  349.  
  350.     yyabort:
  351.             return(1);
  352.  
  353.  
  354.         case 3:  /* no shift yet; clobber input char */
  355.  
  356. #ifdef YYDEBUG
  357.             if( yydebug ) printf( "error recovery discards char %d\n", yychar );
  358. #endif
  359.  
  360.             if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
  361.             yychar = -1;
  362.             goto yynewstate;   /* try again in the same state */
  363.  
  364.             }
  365.  
  366.         }
  367.  
  368.     /* reduction by production yyn */
  369.  
  370. #ifdef YYDEBUG
  371.         if( yydebug ) printf("reduce %d\n",yyn);
  372. #endif
  373.         yyps -= yyr2[yyn];
  374.         yypvt = yypv;
  375.         yypv -= yyr2[yyn];
  376.         yyval = yypv[1];
  377.         yym=yyn;
  378.             /* consult goto table to find next state */
  379.         yyn = yyr1[yyn];
  380.         yyj = yypgo[yyn] + *yyps + 1;
  381.         if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
  382.         switch(yym){
  383.             
  384. case 4:
  385. # line 81 "hoc.y"
  386. { lastno = yypvt[-1].val; printf("\t%.8g\n", yypvt[-1].val); } break;
  387. case 5:
  388. # line 82 "hoc.y"
  389. { yyerrok; } break;
  390. case 6:
  391. # line 84 "hoc.y"
  392. { execerror("can't assign to constant: ", yypvt[-2].sym->name); } break;
  393. case 7:
  394. # line 85 "hoc.y"
  395. { yyval.val = yypvt[-2].sym->u.val = yypvt[-0].val; yypvt[-2].sym->type = VAR; } break;
  396. case 8:
  397. # line 87 "hoc.y"
  398. { yyval.val = yypvt[-0].val; } break;
  399. case 9:
  400. # line 88 "hoc.y"
  401. { yyval.val = yypvt[-0].sym->u.val; } break;
  402. case 10:
  403. # line 89 "hoc.y"
  404. {
  405.         If yypvt[-0].sym->type == UNDEF Do
  406.             execerror("undefined variable: ", yypvt[-0].sym->name);
  407.           Endif
  408.         yyval.val = yypvt[-0].sym->u.val; } break;
  409. case 11:
  410. # line 94 "hoc.y"
  411. { yyval.val = (*(yypvt[-3].sym->u.ptr))(yypvt[-1].val); } break;
  412. case 12:
  413. # line 95 "hoc.y"
  414. {
  415.         yyval.val = (*(yypvt[-5].sym->u.ptr))(yypvt[-3].val, yypvt[-1].val); } break;
  416. case 13:
  417. # line 97 "hoc.y"
  418. { yyval.val = (*(yypvt[-2].sym->u.ptr))(); } break;
  419. case 15:
  420. # line 99 "hoc.y"
  421. { yyval.val = yypvt[-2].val + yypvt[-0].val; } break;
  422. case 16:
  423. # line 100 "hoc.y"
  424. { yyval.val = yypvt[-2].val - yypvt[-0].val; } break;
  425. case 17:
  426. # line 101 "hoc.y"
  427. { yyval.val = yypvt[-2].val * yypvt[-0].val; } break;
  428. case 18:
  429. # line 102 "hoc.y"
  430. {
  431.         If yypvt[-0].val == 0.0 Do
  432.             execerror("division by zero", "");
  433.         Endif
  434.         yyval.val = yypvt[-2].val / yypvt[-0].val; } break;
  435. case 19:
  436. # line 107 "hoc.y"
  437. {    /* definition as per Knuth, v1 */
  438.         If yypvt[-0].val == 0.0 Do
  439.             yyval.val = yypvt[-2].val;
  440.         Elsedo
  441.             yyval.val = yypvt[-2].val - yypvt[-0].val * floor(yypvt[-2].val / yypvt[-0].val);
  442.         Endif } break;
  443. case 20:
  444. # line 113 "hoc.y"
  445. { yyval.val = Pow(yypvt[-2].val, yypvt[-0].val); } break;
  446. case 21:
  447. # line 114 "hoc.y"
  448. { yyval.val = yypvt[-1].val ; } break;
  449. case 22:
  450. # line 115 "hoc.y"
  451. { yyval.val = -yypvt[-0].val; } break;
  452. case 23:
  453. # line 116 "hoc.y"
  454. { yyval.val = yypvt[-0].val; } break;
  455.         }
  456.         goto yystack;  /* stack new state and value */
  457.  
  458.     }
  459.